package com.clss.webrtclibrary;

import android.content.Context;
import android.media.projection.MediaProjection;
import android.support.annotation.Nullable;
import android.text.TextUtils;

import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.CameraEnumerator;
import org.webrtc.CameraVideoCapturer;
import org.webrtc.DataChannel;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpReceiver;
import org.webrtc.ScreenCapturerAndroid;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;
import org.webrtc.StatsReport;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoDecoderFactory;
import org.webrtc.VideoEncoderFactory;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
import org.webrtc.audio.AudioDeviceModule;
import org.webrtc.audio.JavaAudioDeviceModule;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * WebRtc连接管理器
 * @author liuv
 * @date 2018/5/2
 */

public class KurentoPeerManager {
    private static final String TAG = "KurentoPeerManager";

    private static final String TRUE = "true";
    private static final String FALSE = "false";

    private static final int HD_VIDEO_WIDTH = 1280;
    private static final int HD_VIDEO_HEIGHT = 720;

    private PeerConnectionFactory mPeerConnectionFactory;
    private PeerConnection mPublisherPeerConnection = null, mPlayerPeerConnection = null;
    private Map<String, PeerConnection> mRecivePeerConnectionMap = new HashMap<>();
    private MediaStream mLocalStream = null;
    private KurentoServer mKurentoServer;
    private SessionDescription mMySdp = null;
    private Context mContext;
    private boolean isFrontCamera = false;

    private VideoCapturer mCapturer = null;
    private int videoWidth = HD_VIDEO_WIDTH;
    private int videoHeight = HD_VIDEO_HEIGHT;
    private int videoFps = 30;
    private SurfaceTextureHelper mSurfaceTextureHelper;
    private boolean isScreen;
    private boolean isVideoConnected = false;

    @Nullable
    private VideoSource mLocalVideoSource;
    @Nullable
    private VideoTrack mLocalVideoTrack;
    @Nullable
    private AudioSource mLocalAudioSource;
    @Nullable
    private AudioTrack mLocalAudioTrack;

    private final String LOCAL_MEDIA_ID = "1198181";
    private static final ExecutorService executor = Executors.newSingleThreadExecutor();

    public KurentoPeerManager(KurentoServer mKurentoServer, Context context) {
        this.mKurentoServer = mKurentoServer;
        this.mContext = context;
        VideoEncoderFactory encoderFactory;
        VideoDecoderFactory decoderFactory;
//        if (peerConnectionParameters.videoCodecHwAcceleration) {
//            encoderFactory = new DefaultVideoEncoderFactory(
//                    rootEglBase.getEglBaseContext(), true /* enableIntelVp8Encoder */, enableH264HighProfile);
        decoderFactory = new DefaultVideoDecoderFactory(mKurentoServer.getIKurentoGatewayCallbacks().getEglBase().getEglBaseContext());
//        } else {
        Lg.i(TAG, "---initEncode===");
        encoderFactory = new DefaultVideoEncoderFactory(mKurentoServer.getIKurentoGatewayCallbacks().getEglBase().getEglBaseContext(),
                true, false);
//        encoderFactory = new HardwareVideoEncoderFactory(mKurentoServer.getIKurentoGatewayCallbacks().getEglBase().getEglBaseContext(),
//                false, true);
//        decoderFactory = new HardwareVideoDecoderFactory(mKurentoServer.getIKurentoGatewayCallbacks().getEglBase().getEglBaseContext());
//        }
        AudioDeviceModule javaAudioDeviceModule = JavaAudioDeviceModule
                .builder(mContext)
                .setSampleRate(16000)
                .createAudioDeviceModule();
        mPeerConnectionFactory = PeerConnectionFactory
                .builder()
                .setAudioDeviceModule(javaAudioDeviceModule)
                .setVideoEncoderFactory(encoderFactory)
                .setVideoDecoderFactory(decoderFactory)
                .createPeerConnectionFactory();
    }

    /** 获取摄像头视频 */
    private @Nullable
    VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
        final String[] deviceNames = enumerator.getDeviceNames();
        // Front facing camera not found, try something else
        Lg.i(TAG, "Looking for other cameras.");
        for (String deviceName : deviceNames) {
            if (!enumerator.isFrontFacing(deviceName)) {
                Lg.i(TAG, "Creating other camera capturer." + deviceName);
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
                if (videoCapturer != null) {
                    isFrontCamera = false;
                    return videoCapturer;
                }
            }
        }
        // First, try to find front facing camera
        for (String deviceName : deviceNames) {
            if (enumerator.isFrontFacing(deviceName)) {
                Lg.i(TAG, "Creating front facing camera capturer." + deviceName);
                VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
                if (videoCapturer != null) {
                    isFrontCamera = true;
                    return videoCapturer;
                }
            }
        }
        return null;
    }

    /** 视频投屏功能 */
    private VideoCapturer createScreenCapturer(){
        return new ScreenCapturerAndroid(mKurentoServer.getIKurentoGatewayCallbacks().
                getMediaHandleCallback().getScreenIntent(), new MediaProjection.Callback() {
            @Override
            public void onStop() {
                super.onStop();
            }
        });
    }

    /** 外接摄像头 */
    private VideoCapturer createUVCCapturer(){
        return new UVCCameraCapturerAndroid();
    }

    /** 创建本地音轨 */
    @Nullable
    private AudioTrack createAudioTrack() {
        MediaConstraints mediaConstraints = new MediaConstraints();
        mediaConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(ConfigAndUtils.AUDIO_ECHO_CANCELLATION_CONSTRAINT, TRUE));
        mediaConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(ConfigAndUtils.AUDIO_AUTO_GAIN_CONTROL_CONSTRAINT, TRUE));
        mediaConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(ConfigAndUtils.AUDIO_HIGH_PASS_FILTER_CONSTRAINT, TRUE));
        mediaConstraints.mandatory.add(
                new MediaConstraints.KeyValuePair(ConfigAndUtils.AUDIO_NOISE_SUPPRESSION_CONSTRAINT, TRUE));
        mLocalAudioSource = mPeerConnectionFactory.createAudioSource(mediaConstraints);
        mLocalAudioTrack = mPeerConnectionFactory.createAudioTrack(ConfigAndUtils.AUDIO_TRACK_ID, mLocalAudioSource);
        mLocalAudioTrack.setEnabled(true);
        return mLocalAudioTrack;
    }

    /** 创建本地视轨 */
    @Nullable
    private VideoTrack createVideoTrack() {
        mLocalVideoSource = mPeerConnectionFactory.createVideoSource(isScreen);
        mSurfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread",
                mKurentoServer.getIKurentoGatewayCallbacks().getEglBase().getEglBaseContext());
        mCapturer.initialize(mSurfaceTextureHelper, mContext, mLocalVideoSource.getCapturerObserver());
        mCapturer.startCapture(videoWidth, videoHeight, videoFps);
        mLocalVideoTrack = mPeerConnectionFactory.createVideoTrack(ConfigAndUtils.VIDEO_TRACK_ID, mLocalVideoSource);
        if (mKurentoServer.getIKurentoGatewayCallbacks().getVideoTrackEnable() != null){
            mLocalVideoTrack.setEnabled(mKurentoServer.getIKurentoGatewayCallbacks().getVideoTrackEnable());
        }
        return mLocalVideoTrack;
    }

    /** 准备连接webrtc并发布本地视频 */
    public void preparePublishVideo(){
        if (mPublisherPeerConnection == null){
            MediaStream stream = null;
            isScreen = mKurentoServer.getIKurentoGatewayCallbacks().
                    getMediaHandleCallback().getScreenIntent() != null;
//            if (!isScreen){
//                mCapturer = createCameraCapturer(new Camera2Enumerator(mKurentoServer.getContext()));
//            }else {
//                mCapturer = createScreenCapturer();
//            }
            mCapturer = createUVCCapturer();
            createAudioTrack();
            createVideoTrack();
            stream = mPeerConnectionFactory.createLocalMediaStream(LOCAL_MEDIA_ID);
            if (mLocalAudioTrack != null){
                stream.addTrack(mLocalAudioTrack);
            }
            if (mLocalVideoTrack != null){
                stream.addTrack(mLocalVideoTrack);
            }
            mLocalStream = stream;
            if (mLocalStream != null){
                mKurentoServer.getIKurentoGatewayCallbacks().getMediaHandleCallback().onLocalStream(mLocalStream);
            }
            localStreamsDone();
        }else {

        }
    }

    /** 开启或关闭本地和对方的视频轨道 */
    public void setLocalAndRemoteVideoTrackEnable(boolean enable){
        if (mLocalStream != null){
            mLocalStream.videoTracks.get(0).setEnabled(enable);
        }
    }

    /** 切换摄像头 */
    public boolean switchCameraInternal() {
        if (mCapturer instanceof CameraVideoCapturer) {
            executor.execute(() -> {
                CameraVideoCapturer cameraVideoCapturer = (CameraVideoCapturer) mCapturer;
                cameraVideoCapturer.switchCamera(null);
            });
            return isFrontCamera = !isFrontCamera;
        } else {
            Lg.e(TAG, "Will not switch camera, video caputurer is not a camera");
            return isFrontCamera;
        }
    }

    /**
     * 本地流已经准备好，可以发布了，创建发布的PeerConnection，把本地流放进去，并为之创建新的sdp信息
     */
    private void localStreamsDone() {
        mPublisherPeerConnection = mPeerConnectionFactory.createPeerConnection(mKurentoServer.getIceServers(),
                new KurentoPeerConnectionObserver());
        if (mLocalStream != null){
            mPublisherPeerConnection.addStream(mLocalStream);
        }
        mPublisherPeerConnection.createOffer(new KurentoSdpObserver(null), getMediaConstraints());

    }

    /**
     * 设置远端设备的sdp信息到本地
     * @param sdp 远端sdp信息
     * @param name 监听目标的id，如果自己是publiser，name填null
     */
    public void setRemoteSdp(String sdp, String name){
        SessionDescription.Type type = SessionDescription.Type.ANSWER;
        SessionDescription sessionDescription = new SessionDescription(type, sdp);
        if (TextUtils.isEmpty(name)) {
            Lg.i(TAG, "---setRemoteSdp===name===null");
            mPublisherPeerConnection.setRemoteDescription(new KurentoSdpObserver(null),
                    sessionDescription);
        }else {
            Lg.i(TAG, "---setRemoteSdp===name===" + name);
            mRecivePeerConnectionMap.get(name).setRemoteDescription(new KurentoSdpObserver(name),
                    sessionDescription);
        }
    }

    /**
     * 发布本地的iceCandidate
     * @param iceCandidate
     * @param name  监听目标的name
     */
    private void sendIceCandidate(IceCandidate iceCandidate, String name, boolean isPlay){
        Lg.i(TAG, "---sendIceCandidate===" + isPlay + "===IceCandidate===" + iceCandidate);
        KurentoSignallingBean bean = new KurentoSignallingBean();
        bean.setId(KurentoSignActionType.onIceCandidate.name());
        bean.setCandidate(new KurentoSignallingBean.Candidate(iceCandidate.sdp, iceCandidate.sdpMid, iceCandidate.sdpMLineIndex));
        if (isPlay){
            bean.setPlayer(name);
        }else {
            bean.setRoom(mKurentoServer.getMediaInfoBean().getId());
            bean.setName(TextUtils.isEmpty(name) ? mKurentoServer.getMyId() : name);
        }
        mKurentoServer.sendMessage(bean);
    }

    /**
     * 设置远端的iceCandidate到本地配置
     * @param sdpMid
     * @param sdpMLineIndex
     * @param candidate
     * @param name 监听目标的id，如果自己是publiser，name填null
     */
    public void setRemoteIceCandidate(String sdpMid, int sdpMLineIndex, String candidate, String name, boolean isPlayer){
        Lg.i(TAG, "---setRemoteIceCandidate===" + isPlayer);
        IceCandidate iceCandidate = new IceCandidate(sdpMid, sdpMLineIndex, candidate);
        if (isPlayer){
            //如果是播放模式
            mPlayerPeerConnection.addIceCandidate(iceCandidate);
        }else {
            //如果是不是播放模式
            if (mKurentoServer.getMyId().equals(name)){
                //如果是自己发布视频peerConnection的ice信息
                if (mPublisherPeerConnection != null) {
                    mPublisherPeerConnection.addIceCandidate(iceCandidate);
                }
            }else {
                //如果是接收视频peerConnection的ice信息，找到对应人的peerConnection并把信息设置进去
                if (mRecivePeerConnectionMap.containsKey(name)) {
                    Lg.i(TAG, "---setRemoteIceCandidate===mRecivePeerConnectionMap.containsKey(name)===" + name);
                    mRecivePeerConnectionMap.get(name).addIceCandidate(iceCandidate);
                }
            }
        }
    }

    /**
     * 准备监听远端的媒体流
     * @param name 监听目标的id，如果自己是publiser，name填null
     */
    public void prepareReceiveRemoteMedia(String name){
        Lg.i(TAG, "---prepareReceiveRemoteMedia===" + name);
        if (mRecivePeerConnectionMap.containsKey(name)){
            mKurentoServer.getIKurentoGatewayCallbacks().getMediaHandleCallback().onRemoteStream(null, name);
            return;
        }
        PeerConnection peerConnection = mPeerConnectionFactory.createPeerConnection(mKurentoServer.getIceServers(),
                new KurentoPeerConnectionObserver(name));
        mRecivePeerConnectionMap.put(name, peerConnection);
        peerConnection.createOffer(new KurentoSdpObserver(name), getMediaConstraints());
    }

    /**
     * 检查连接的状态
     */
    public void checkPeerConnectionStatus(){
        Lg.i(TAG, "---stats=checkPeerConnectionStatus===");
//        if (mPublisherPeerConnection != null){
//            mPublisherPeerConnection.getStats(rtcStatsReport -> {
////                Lg.i(TAG, "---rtcStatsReport.toString===" + rtcStatsReport.toString());
//                Lg.i(TAG, "---stats=rtcStatsReport.getTimestampUs===" + rtcStatsReport.getTimestampUs());
//                for(Map.Entry<String, RTCStats> entry : rtcStatsReport.getStatsMap().entrySet()){
//                    Lg.e(TAG, "---stats=rtcStatsReport.entry===" + entry.getKey());
//                    Lg.i(TAG, "---stats=rtcStatsReport.entry===" + entry.getValue());
//                }
//            });
//        }
        if (mPublisherPeerConnection != null){
            mPublisherPeerConnection.getStats(statsReports -> {
                Lg.i(TAG, "---stats=publish==statsReports===" + statsReports);
                for (StatsReport s : statsReports) {
                    Lg.i(TAG, "---statsReports===" + s.toString());
                    if (s.type.equals("ssrc") && s.id.contains("_send")
                            && AppRTCUtils.getStateReportValue(s.values, "mediaType").equals("video")) {
                        String time = AppRTCUtils.getStateReportValue(s.values, "googRtt");
                        if (time.isEmpty()){
                            return;
                        }
                        Lg.i(TAG, "---stats=time==" + time);
                        Lg.i(TAG, "---stats=isVideoConnected==" + isVideoConnected);
                        if (isVideoConnected){
                            if (time.equals("0")){
                                Lg.e(TAG, "---stats=视频断开了==");
                                mKurentoServer.onVideoState("VIDEO_IS_DISCONNECTED");
//                                Looper.prepare();
//                                Toast.makeText(mContext, "视频已断开", Toast.LENGTH_SHORT).show();
//                                Looper.loop();
                            }
                            if (mKurentoServer != null){
                                mKurentoServer.publishConnectionInfo("videoStatus:" +
                                        AppRTCUtils.getStateReportValue(s.values, "googFrameWidthInput") + "," +
                                        AppRTCUtils.getStateReportValue(s.values, "googFrameHeightInput") + "," +
                                        AppRTCUtils.getStateReportValue(s.values, "googFrameWidthSent") + "," +
                                        AppRTCUtils.getStateReportValue(s.values, "googFrameHeightSent"));
                            }
                        }else {
                            if (!time.equals("0")){
                                isVideoConnected = true;
                            }
                        }
                    }
                }
            }, null);
        }
//        if(mRecivePeerConnectionMap.size() > 0){
//            for (Map.Entry<String, PeerConnection> entry : mRecivePeerConnectionMap.entrySet()){
//                entry.getValue().getStats(statsReports -> {
//                    Lg.i(TAG, "---remote==statsReports===" + statsReports.length);
//                    for (StatsReport s : statsReports){
//                        Lg.i(TAG, "---stats=remote=report==" + s.toString());
//                        for (StatsReport.Value v : s.values){
//                            if (v.name.equals("googCurrentDelayMs")){
//                                if (s.toString().contains("mediaType: audio")){
//                                    Lg.i(TAG, "---remote=audio=delay=" + v.value);
//                                }else if (s.toString().contains("mediaType: video")){
//                                    Lg.i(TAG, "---remote=video=delay=" + v.value);
//                                }
//                            }
//                        }
//                    }
//                }, null);
//            }
//        }
    }

    /**
     * 设置本地peerConnection的sdp信息并发送给远端
     * @param sessionDescription
     * @param name 监听目标的id，如果自己是publiser，name填null
     */
    private void sendLocalSdpInfo(SessionDescription sessionDescription, String name){
        Lg.i(TAG, "---sendLocalSdpInfo===");
        KurentoSignallingBean bean = new KurentoSignallingBean();
        bean.setRoom(mKurentoServer.getMediaInfoBean().getId());
        if (mPublisherPeerConnection != null && TextUtils.isEmpty(name)){
            Lg.i(TAG, "---sendLocalSdpInfo===mPublisherPeerConnection != null && TextUtils.isEmpty(name)");
            if (mMySdp == null){
                mMySdp = sessionDescription;
                mPublisherPeerConnection.setLocalDescription(new KurentoSdpObserver(null), sessionDescription);
            }
            bean.setId(KurentoSignActionType.publish.name());
            bean.setSdpOffer(mMySdp.description);
            String cTag = mKurentoServer.getMediaInfoBean().getSignalingBean().getCompositeTag();
            if (!TextUtils.isEmpty(cTag)){
                bean.setCompositeTag(cTag);
            }
            String vTag = mKurentoServer.getMediaInfoBean().getSignalingBean().getVideoTag();
            if (!TextUtils.isEmpty(vTag)) {
                bean.setVideoTag(vTag);
            }
            mKurentoServer.sendMessage(bean);
        }
        if (mRecivePeerConnectionMap.get(name) != null && !TextUtils.isEmpty(name)){
            Lg.i(TAG, "---sendLocalSdpInfo===mRecivePeerConnectionMap.get(name) != null && !TextUtils.isEmpty(name)");
            mRecivePeerConnectionMap.get(name).setLocalDescription(new KurentoSdpObserver(name), sessionDescription);
            bean.setId(KurentoSignActionType.receiveVideoFrom.name());
            bean.setSdpOffer(sessionDescription.description);
            bean.setSender(name);
            mKurentoServer.sendMessage(bean);
        }
    }

    /**
     * 取消对某人的监听
     * @param name 某人的ID
     */
    public void cancelReceivePublisher(String name){
        mKurentoServer.sendCancelReceiveVideo(name);
        mKurentoServer.getIKurentoGatewayCallbacks().getMediaHandleCallback().onRemoveRemoteStream(name);
        if (mRecivePeerConnectionMap.containsKey(name)){
            closePeerConnection(mRecivePeerConnectionMap.get(name));
            mRecivePeerConnectionMap.remove(name);
        }
    }

    public void removeRemoteIceCandidates(IceCandidate[] iceCandidateArray){
        mPublisherPeerConnection.removeIceCandidates(iceCandidateArray);
    }

    public void stopVideoConnection(){
        executor.execute(this::closeAndDisposePeerConnectioned);
    }

    /**
     * 关闭所有视频通道，所有变量dispose后置空
     */
    public void closeAndDisposePeerConnectioned(){
        Lg.i(TAG, "---closeAndDisposePeerConnection===");
        if (mPublisherPeerConnection != null){
            closePeerConnection(mPublisherPeerConnection);
            if (mLocalAudioSource != null) {
                mLocalAudioSource.dispose();
                mLocalAudioSource = null;
            }

            if (mCapturer != null) {
                try {
                    mCapturer.stopCapture();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                mCapturer.dispose();
                mCapturer = null;
            }

            if (mLocalVideoSource != null){
                mLocalVideoSource.dispose();
                mLocalVideoSource = null;
            }
            mLocalStream = null;
        }
        if (mRecivePeerConnectionMap != null){
            for (Map.Entry<String, PeerConnection> entry : mRecivePeerConnectionMap.entrySet()){
                closePeerConnection(entry.getValue());
            }
            mRecivePeerConnectionMap.clear();
        }
        if (mPlayerPeerConnection != null){
            closePeerConnection(mPlayerPeerConnection);
        }
        if (mPeerConnectionFactory != null) {
            mPeerConnectionFactory.dispose();
            mPeerConnectionFactory = null;
        }
        PeerConnectionFactory.stopInternalTracingCapture();
        PeerConnectionFactory.shutdownInternalTracer();
        mContext = null;
    }

    private void closePeerConnection(PeerConnection peerConnection){
        peerConnection.close();
        peerConnection.dispose();
    }

    public Map<String, PeerConnection> getRecivePeerConnectionMap() {
        return mRecivePeerConnectionMap;
    }

    /**
     * 开始播放录像
     */
    public void startPlayRecord(String player){
        Lg.i(TAG, "---startPlayRecord===");
        mPlayerPeerConnection = mPeerConnectionFactory.createPeerConnection(mKurentoServer.getIceServers(),
                new KurentoPeerConnectionObserver(player, true));
        mPlayerPeerConnection.createOffer(new KurentoSdpObserver(player, true), getMediaConstraints());
    }

    /**
     * 发送播放视频连接本地sdp信息
     * @param sessionDescription
     * @param name
     */
    private void sendPlayerLocalSdpInfo(SessionDescription sessionDescription, String name){
        Lg.i(TAG, "---sendPlayerLocalSdpInfo===" + name);
        mPlayerPeerConnection.setLocalDescription(new KurentoSdpObserver(name, true), sessionDescription);
        KurentoSignallingBean bean = new KurentoSignallingBean();
        bean.setId(KurentoSignActionType.start.name());
        bean.setPlayer(name);
        bean.setSdpOffer(sessionDescription.description);
        mKurentoServer.sendMessage(bean);
    }

    /**
     * 设置播放视频连接远端sdp信息
     * @param sdp
     * @param player
     */
    public void setPlayerRemoteSdpInfo(String sdp, String player){
        Lg.i(TAG, "---setPlayerRemoteSdpInfo===" + sdp);
        SessionDescription.Type type = SessionDescription.Type.ANSWER;
        SessionDescription sessionDescription = new SessionDescription(type, sdp);
        mPlayerPeerConnection.setRemoteDescription(new KurentoSdpObserver(player, true),
                sessionDescription);
    }

    private MediaConstraints getMediaConstraints(){
        MediaConstraints mediaConstraints = new MediaConstraints();
        mediaConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("googCpuOveruseDetection", "true"));
//        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("minWidth", HD_VIDEO_WIDTH + ""));
//        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxWidth", HD_VIDEO_WIDTH * 2 + ""));
//        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("minHeight", HD_VIDEO_HEIGHT + ""));
//        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxHeight", HD_VIDEO_HEIGHT * 2 + ""));

//        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("idealWidth", "0"));
//        mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("idealHeight", "0"));
        return mediaConstraints;
    }

    /**
     * 创建sdp信息的实现类
     */
    private class KurentoSdpObserver implements SdpObserver {

        private String name = null;
        private boolean isPlayer = false;

        KurentoSdpObserver(String name) {
            this.name = name;
        }

        KurentoSdpObserver(String name, boolean isPlayer) {
            this.name = name;
            this.isPlayer = isPlayer;
        }

        @Override
        public void onCreateSuccess(SessionDescription sessionDescription) {
            Lg.i(TAG, "---onCreateSuccess===isPlayer===" + isPlayer);
            if (isPlayer) {
                sendPlayerLocalSdpInfo(sessionDescription, name);
            } else {
                sendLocalSdpInfo(sessionDescription, name);
            }
        }

        @Override
        public void onSetSuccess() {
            Lg.i(TAG, "---onSetSuccess===");
        }

        @Override
        public void onCreateFailure(String s) {
            Lg.i(TAG, "---onCreateFailure===" + s);
        }

        @Override
        public void onSetFailure(String s) {
            Lg.i(TAG, "---onSetFailure===" + s);
        }
    }

    /**
     * 生成ice信息的实现
     */
    private class KurentoPeerConnectionObserver implements PeerConnection.Observer{
        /** name 监听目标的id，如果自己是publiser，name填null */
        private String name = null;
        private boolean isPlayer = false;

        KurentoPeerConnectionObserver() {}

        KurentoPeerConnectionObserver(String name) {
            this.name = name;
        }

        KurentoPeerConnectionObserver(String name, boolean isPlayer) {
            Lg.i(TAG, "---KurentoPeerConnectionObserver===" + name);
            this.name = name;
            this.isPlayer = isPlayer;
        }

        @Override
        public void onSignalingChange(PeerConnection.SignalingState signalingState) {
            Lg.i(TAG, "---onSignalingChange===" + signalingState.toString());
            if (mKurentoServer != null){
                mKurentoServer.publishConnectionInfo("onSignalingChange:" + signalingState.toString());
            }
        }

        @Override
        public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) {
            Lg.i(TAG, "---onIceConnectionChange===" + iceConnectionState.toString());
            if (mKurentoServer != null){
                mKurentoServer.publishConnectionInfo("onIceConnectionChange:" + iceConnectionState.toString());
            }
        }

        @Override
        public void onIceConnectionReceivingChange(boolean b) {
            Lg.i(TAG, "---onIceConnectionReceivingChange===" + b);
        }

        @Override
        public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
            Lg.i(TAG, "---onIceGatheringChange===" + iceGatheringState.toString());
        }

        @Override
        public void onIceCandidate(IceCandidate iceCandidate) {
            Lg.i(TAG, "---onIceCandidate===" + iceCandidate.toString());
            sendIceCandidate(iceCandidate, name, isPlayer);
        }

        @Override
        public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) {
            Lg.i(TAG, "---onIceCandidatesRemoved===");
        }

        @Override
        public void onAddStream(MediaStream mediaStream) {
            Lg.i(TAG, "---onAddStream===" + mediaStream);
            mKurentoServer.getIKurentoGatewayCallbacks().getMediaHandleCallback().onRemoteStream(mediaStream, name);
        }

        @Override
        public void onRemoveStream(MediaStream mediaStream) {
            Lg.i(TAG, "---onRemoveStream===" + mediaStream);
        }

        @Override
        public void onDataChannel(DataChannel dataChannel) {
            Lg.i(TAG, "---onDataChannel===");
        }

        @Override
        public void onRenegotiationNeeded() {
            Lg.i(TAG, "---onRenegotiationNeeded===");
        }

        @Override
        public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) {
            Lg.i(TAG, "---onAddTrack===" + rtpReceiver.toString());

        }
    }
}
